#region Imports

using System;
using System.Collections.Generic;

#endregion

namespace bGallery.Core.Domain
{
	[Serializable]
	public class Category 
	{
		#region Private Members

		// State variables
		private bool isChanged;
		private bool isDeleted;

		// Primary Key(s) 
		private int id; 
		
		// Foreign Keys mappate come Many-To-One 
		private Category parentCategory; 
		
		// Properties 
		private string name; 
		private string abbreviation; 
		private string description; 
		
		// One-to-many relations 
		private IList<Category> subCategories;		

		#endregion
		
		#region Default ( Empty ) Class Constructor
		
		/// <summary>
		/// default constructor
		/// </summary>
		public Category()
		{
			id = 0; 
			parentCategory = null; 
			name = null; 
			abbreviation = null; 
			description = null; 
			subCategories = null; 
		}
		
		#endregion // End of Default ( Empty ) Class Constructor
		
		#region Full Constructor
		
		/// <summary>
		/// full constructor
		/// </summary>
		public Category(int id, Category idcategory, string name, string abbreviation, string description)
		{
			this.id = id;
			this.parentCategory = idcategory;
			this.name = name;
			this.abbreviation = abbreviation;
			this.description = description;
			this.subCategories = null; 
		}
		
		#endregion // End Full Constructor
		
		#region Required Fields Only Constructor
		
		/// <summary>
		/// required (not null) fields only constructor
		/// </summary>
		public Category(int id, string name, string abbreviation)
		{
			this.id = id;
			this.parentCategory = null;
			this.name = name;
			this.abbreviation = abbreviation;
			this.description = null;
			this.subCategories = null; 
		}
		
		#endregion // End Required Fields Only Constructor

		#region Public Properties
			
		/// <summary>
		/// Unique identifier
		/// </summary>		
		public virtual int Id
		{
			get { return id; }
			set { isChanged |= (id != value); id = value; }
		} 
	  
		/// <summary>
		/// Parent category. If null, then it's top category
		/// </summary>		
		public virtual Category ParentCategory
		{
			get { return parentCategory; }
			set { isChanged |= (parentCategory != value); parentCategory = value; }
		} 
	  
		/// <summary>
		/// Name of category
		/// </summary>		
		public virtual string Name
		{
			get { return name; }
			set	
			{
				if ( value != null )
					if( value.Length > 50)
						throw new ArgumentOutOfRangeException("Invalid value for Name", value, value.ToString());
				
				isChanged |= (name != value); name = value;
			}
		} 
	  
		/// <summary>
		/// URL friendly name
		/// </summary>		
		public virtual string Abbreviation
		{
			get { return abbreviation; }
			set	
			{
				if ( value != null )
					if( value.Length > 50)
						throw new ArgumentOutOfRangeException("Invalid value for Abbreviation", value, value.ToString());
				
				isChanged |= (abbreviation != value); abbreviation = value;
			}
		} 
	  
		/// <summary>
		/// Short text description of category
		/// </summary>		
		public virtual string Description
		{
			get { return description; }
			set	
			{
				if ( value != null )
					if( value.Length > 250)
						throw new ArgumentOutOfRangeException("Invalid value for Description", value, value.ToString());
				
				isChanged |= (description != value); description = value;
			}
		} 
	  
		/// <summary>
		/// 
		/// </summary>		
		public virtual IList<Category> SubCategories
		{
			get { return subCategories; }
			set { isChanged |= (subCategories != value); subCategories = value; }
		} 
	  
		/// <summary>
		/// Returns whether or not the object has changed it's values.
		/// </summary>
		public virtual bool IsChanged
		{
			get { return isChanged; }
		}
		
		/// <summary>
		/// Returns whether or not the object has changed it's values.
		/// </summary>
		public virtual bool IsDeleted
		{
			get { return isDeleted; }
		}
		
		/// <summary>
		/// Returns parent ID or -1 if it's top category
		/// </summary>
		public virtual int ParentId
		{
			get { return (this.parentCategory == null ? 0 : this.parentCategory.Id); }
		}

		#endregion 
		
		#region Public Functions

		/// <summary>
		/// mark the item as deleted
		/// </summary>
		public virtual void MarkAsDeleted()
		{
			isDeleted = true;
			isChanged = true;
		}
		
		#endregion
		
		#region Equals And HashCode Overrides
		
		/// <summary>
		/// local implementation of Equals based on unique value members
		/// </summary>
		public override bool Equals( object obj )
		{
			if( this == obj ) return true;
			if( ( obj == null ) || ( obj.GetType() != this.GetType() ) ) return false;
			Category castObj = (Category)obj; 
			return ( castObj != null ) &&
				( this.id == castObj.Id );
		}
		
		/// <summary>
		/// local implementation of GetHashCode based on unique value members
		/// </summary>
		public override int GetHashCode()
		{ 
			int hash = 57; 
			hash = 27 * hash * this.id.GetHashCode();
					
			return hash;		
			
		}
		
		#endregion
		
	}
}